package Controllers;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Observable;
import java.util.Observer;






import Entities.InitiateSaleEntity;
import GUI.WorkDivisionGUI;
import Server.RsWraper;
import Server.Tuple;

/**
 * The Class WorkDivisionController.
 * Controller for dividing the work between sales men in
 * a new sale activity.
 */
public class WorkDivisionController implements Observer,Validate{
	
	
	/** The work division gui. */
	private WorkDivisionGUI workDivisionGUI;
	
	/** The initiate sale entity. */
	private InitiateSaleEntity initiateSaleEntity;
	
	/** The previous. */
	private InitiateSaleController prev;
	
	/** The divide value. */
	private int divideValue;
	
	/** The divide modulo. */
	private int divideModulo;
	
	/** The low value amount. */
	private int lowValueAmount;
	
	/** The customers amount. */
	private int customersAmount;
	
	/** The employees amount. */
	private int employeesAmount;
	
	/** The customers list. */
	private String [] customersList;
	
	/** The customers list locations. */
	private ArrayList<int []>lcustomersLocations=new ArrayList<int []>();
	
	/** The employees combo box locations. */
	private ArrayList<Integer>cemployeesLocations= new ArrayList<Integer>();
	
	/** The employees. */
	private ArrayList<Tuple> employees;
	
	/** The customers. */
	private ArrayList<Tuple> customers;
	
	/** The sale id. */
	private ArrayList<Tuple>saleId=new ArrayList<Tuple>();
	
	/** The employee chosen index. */
	int employeeChosenIndex;
	
	/** The operation. */
	int operation;
	
	/** The selected indices. */
	int[] selectedIndices;
	
	/** The total selected indices. */
	int totalSelectedIndices=0;
	
	/** The employee index. */
	int eIndex;
	
	/**
	 * Instantiates a new work division controller.
	 *
	 * @param workDivisionGUI the work division gui
	 * @param initiateSaleEntity the initiate sale entity
	 */
	public WorkDivisionController(WorkDivisionGUI workDivisionGUI,InitiateSaleEntity initiateSaleEntity) {
		this.workDivisionGUI = workDivisionGUI;
		this.initiateSaleEntity = initiateSaleEntity;
		addEmployeesToCb();	
		this.workDivisionGUI.addAssignActionListener(new AssignListener());
		this.workDivisionGUI.addFinishActionListener(new FinishListener());
		this.workDivisionGUI.addBackActionListener(new BackListener());
		this.workDivisionGUI.setVisible(true);			
	}
	
	

	/**
	 * Adds the customers to the list.
	 */
	private void addCustomersToList() {
		ClientController.setObserver(new ListObserver());
		String query = "SELECT users.uid,users.name FROM users,authorizations,customers WHERE authorizations.cid=customers.cid AND users.uid = authorizations.cid AND users.uid = customers.cid AND authorizations.pid = '"+initiateSaleEntity.getPid()+"' AND  users.age >= '"+initiateSaleEntity.getAge()+ "' AND users.livingarea= '"+initiateSaleEntity.getLivingArea()+"' AND customers.importancerank >= '"+initiateSaleEntity.getImportancerank()+"' AND authorizations.interestlevel >= '"+initiateSaleEntity.getInterestlevel()+"'";
		try {
			ClientController.observableClient.sendToServer(query);
		} catch (IOException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		
	}

	
	/**
	 * Adds the employees to the combo box.
	 */
	private void addEmployeesToCb()
	{
		ClientController.setObserver(new employeeCbInsert());
		String query = "SELECT users.uid,users.name FROM users,employees WHERE users.uid = employees.eid AND employees.position ='SM'";
		try {
			ClientController.observableClient.sendToServer(query);
		} catch (IOException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		
	}
	
	/**
	 * An asynchronous update interface for receiving notifications
	 * about List information as the List is constructed.
	 */
	class ListObserver implements Observer
	{
		
		
		/* (non-Javadoc)
		 * @see java.util.Observer#update(java.util.Observable, java.lang.Object)
		 */
		@Override
		public void update(Observable o, Object arg) {
			if(!arg.toString().equals("empty query"))
			{
			customers=new ArrayList<Tuple>();
			customers.addAll(((RsWraper)arg).getRows());		//appends all customers list
			customersList=new String[customers.size()];
			for(int i=0;i<customers.size();i++)
			{
				//customersList[i]=customers.get(i).get("UID")+","+customers.get(i).get("NAME");
				workDivisionGUI.getcListModel().addElement(customers.get(i).get("UID")+","+customers.get(i).get("NAME"));
			}
			customersAmount=customers.size();
			divideValue=customersAmount/employeesAmount;//minimum=divideValue
			divideModulo=customersAmount%employeesAmount;//amount of employees that serves minimum+1 amount of customers
			if(divideValue>0)
				lowValueAmount=employeesAmount-divideModulo;//amount of employees that serve the minimum amount of customers
			else
				lowValueAmount=0;
			//workDivisionGUI.getCustomersList().setListData(customersList);	
			ClientController.setObserver(WorkDivisionController.this);
			}
			else
				workDivisionGUI.displayWarningMessage("There are no matching customers,please choose a different marketing pattern.");

		}
		
	}
	
	/**
	 * The Class employeeCbInsert implements Observer.
	 * Used for inserting the employees info from data base to the combo box
	 */
	class employeeCbInsert implements Observer{

		/* (non-Javadoc)
		 * @see java.util.Observer#update(java.util.Observable, java.lang.Object)
		 */
		@Override
		public void update(Observable arg0, Object arg1) {
			if(!arg1.toString().equals("empty query"))
			{
			employees=new ArrayList<Tuple>();
			employees.addAll(((RsWraper)arg1).getRows());		//appends all employees list
			for(int i=0;i<employees.size();i++)
			{
				workDivisionGUI.geteCbModel().addElement(employees.get(i).get("UID")+","+employees.get(i).get("NAME"));
			}
			employeesAmount=employees.size();
			addCustomersToList();
			}
			else
				workDivisionGUI.displayWarningMessage("There are no sales men!");
		}
		
	}


	/**
	 * The listener interface for receiving assign events.
	 * The class that is interested in processing a assign
	 * event implements this interface, and the object created
	 * with that class is registered with a component using the
	 * component's addAssignListener  method. When
	 * the assign event occurs, that object's appropriate
	 * method is invoked.
	 *
	 */
	class AssignListener implements ActionListener
	{
		
		
		/* (non-Javadoc)
		 * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
		 */
		@Override
		public void actionPerformed(ActionEvent e) {
			if(validateInput())
			{

				int k=0;
				String [] str;
				selectedIndices=new int[workDivisionGUI.getCustomersList().getSelectedValues().length];
				
				for (int i = 0; i < customers.size(); i++) {
				for (int j = 0; j < workDivisionGUI.getCustomersList().getSelectedValues().length; j++) {
					str=workDivisionGUI.getCustomersList().getSelectedValuesList().get(j).split(",");
					if(customers.get(i).get("UID").equals(str[0]))
					{
						selectedIndices[k]=i;
						k++;
						j=workDivisionGUI.getCustomersList().getSelectedValues().length;
					}
				}
				}
				
			
				String str1=(String) workDivisionGUI.getEmployeesComboBox().getSelectedItem();
				String[] str2=str1.split(",");
				for (int i = 0; i < employees.size(); i++) {
					if(employees.get(i).get("UID").equals(str2[0]))
					{
						eIndex=i;
					}
				}
				
				lcustomersLocations.add(selectedIndices);
				cemployeesLocations.add(eIndex);
				Object [] objects=workDivisionGUI.getCustomersList().getSelectedValues();
				workDivisionGUI.geteCbModel().removeElement(workDivisionGUI.getEmployeesComboBox().getSelectedItem());
						
				int temp=workDivisionGUI.getCustomersList().getSelectedValues().length;
				for (int i = 0; i < temp; i++) {
					workDivisionGUI.getcListModel().removeElement(objects[i]);
				
				}	
				workDivisionGUI.getCustomersList().validate();
				workDivisionGUI.getEmployeesComboBox().validate();
				if(lowValueAmount!=0||divideModulo!=0)
				workDivisionGUI.displayWarningMessage("Continue to choose");
			}
			else
			{
				workDivisionGUI.displayWarningMessage("Wrong division, choose again");
				workDivisionGUI.getCustomersList().clearSelection();
			}
		}
		
	}
	
	/**
	 * The listener interface for receiving finish events.
	 * The class that is interested in processing a finish
	 * event implements this interface, and the object created
	 * with that class is registered with a component using the
	 * component's addFinishListener method. When
	 * the finish event occurs, that object's appropriate
	 * method is invoked.
	 *
	 */
	class FinishListener implements ActionListener
	{

		/* (non-Javadoc)
		 * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
		 */
		@Override
		public void actionPerformed(ActionEvent e) {
			if(lowValueAmount==0&&divideModulo==0)
			{
				String query="INSERT INTO sales (`mpid`, `date`, `period`, `location`) VALUES ('"+Integer.parseInt(initiateSaleEntity.getMpid())+"', '"+initiateSaleEntity.getDate()+"', '"+initiateSaleEntity.getPeriod()+"', '"+initiateSaleEntity.getLivingArea()+"')";
				try {
					operation=0;
					ClientController.observableClient.sendToServer(query);
				} catch (IOException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}	
				
			}
			else
				workDivisionGUI.displayWarningMessage("You need to finish the Division first");
		}
		
	}

	/**
	 * The listener interface for receiving back events.
	 * The class that is interested in processing a back
	 * event implements this interface, and the object created
	 * with that class is registered with a component using the
	 * component's addBackListener method. When
	 * the back event occurs, that object's appropriate
	 * method is invoked.
	 *
	 */
	class BackListener implements ActionListener
	{

		/* (non-Javadoc)
		 * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
		 */
		@Override
		public void actionPerformed(ActionEvent e) {
			LoginController.mainWindow.setTitle("Initiate sale");
			LoginController.mainWindow.setContentPane(prev.getInitiateSaleGUI());

		}
		
	}
	
	/* (non-Javadoc)
	 * @see java.util.Observer#update(java.util.Observable, java.lang.Object)
	 */
	@Override
	public void update(Observable arg0, Object arg1) {
		if(arg1.toString().equals("error"))
		{
			workDivisionGUI.displayWarningMessage("The same sale is already exists");
		}
		else if(arg1.toString().equals("#Server:Action succeded")&&operation==0)
		{
			String query = "SELECT sales.sid FROM sales WHERE sales.mpid= '"+Integer.parseInt(initiateSaleEntity.getMpid())+"' AND sales.date= '"+initiateSaleEntity.getDate()+"' AND sales.period= '"+initiateSaleEntity.getPeriod()+"' AND sales.location= '"+initiateSaleEntity.getLivingArea()+"'" ;
			operation=1;
			try {
				ClientController.observableClient.sendToServer(query);
			} catch (IOException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
		}
		else if(operation==1)
		{
			saleId.addAll(((RsWraper)arg1).getRows());
			String query="INSERT INTO servesinsale (`sid`, `eid`, `cid`) VALUES ";
			for (employeeChosenIndex = 0; employeeChosenIndex < cemployeesLocations.size(); employeeChosenIndex++) {
				for (int i= 0; i < lcustomersLocations.get(employeeChosenIndex).length; i++) {
					if(employeeChosenIndex==(cemployeesLocations.size()-1)&&i==lcustomersLocations.get(employeeChosenIndex).length-1)
						query+="('"+saleId.get(0).get("SID")+"', '"+employees.get(cemployeesLocations.get(employeeChosenIndex)).get("UID")+"', '"+customers.get(lcustomersLocations.get(employeeChosenIndex)[i]).get("UID") +"')";
					else
					query+="('"+saleId.get(0).get("SID")+"', '"+employees.get(cemployeesLocations.get(employeeChosenIndex)).get("UID")+"', '"+customers.get(lcustomersLocations.get(employeeChosenIndex)[i]).get("UID") +"'),";

				}
			}
			try {
			
				operation=3;
				ClientController.observableClient.sendToServer(query);
			} catch (IOException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
	
			workDivisionGUI.displayMessage("Initiate sale succeded");
			LoginController.mainWindow.setContentPane(prev.getPrev().getMarketingManagerGui());
		}

	}

	

	/* (non-Javadoc)
	 * @see Controllers.Validate#validateInput()
	 */
	@Override
	public boolean validateInput() {
		if(workDivisionGUI.getCustomersList().isSelectionEmpty()||workDivisionGUI.getEmployeesComboBox().getSelectedItem()==null)
		return false;
		if(workDivisionGUI.getCustomersList().getSelectedValuesList().size()==divideValue&&lowValueAmount>0)
		{
			lowValueAmount--;
			return true;
		}
		else if(workDivisionGUI.getCustomersList().getSelectedValuesList().size()==(divideValue+1)&&divideModulo>0)
		{
			divideModulo--;
			return true;
		}
		return false;
	}
	
	/**
	 * Gets the work division gui.
	 *
	 * @return the work division gui
	 */
	public WorkDivisionGUI getWorkDivisionGUI() {
		return workDivisionGUI;
	}

	/**
	 * Sets the work division gui.
	 *
	 * @param workDivisionGUI the new work division gui
	 */
	public void setWorkDivisionGUI(WorkDivisionGUI workDivisionGUI) {
		this.workDivisionGUI = workDivisionGUI;
	}

	/**
	 * Gets the previous controller.
	 *
	 * @return the previous controller
	 */
	public InitiateSaleController getPrev() {
		return prev;
	}

	/**
	 * Sets the previous controller.
	 *
	 * @param prev the new previous controller
	 */
	public void setPrev(InitiateSaleController prev) {
		this.prev = prev;
	}


}
